package com.seecen.HJM.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.seecen.HJM.constant.JwtClaimsConstant;
import com.seecen.HJM.constant.MessageConstant;
import com.seecen.HJM.enumeration.RoleEnum;
import com.seecen.HJM.mapper.UserMapper;
import com.seecen.HJM.model.dto.UserLoginDTO;
import com.seecen.HJM.model.dto.UserResetPasswordDTO;
import com.seecen.HJM.model.entity.User;
import com.seecen.HJM.model.vo.UserVO;
import com.seecen.HJM.result.DataVo;
import com.seecen.HJM.service.EmailService;
import com.seecen.HJM.service.IUserService;
import com.seecen.HJM.service.MinioService;
import com.seecen.HJM.util.JwtUtil;
import com.seecen.HJM.util.PasswordEncoderUtil;
import com.seecen.HJM.util.ThreadLocalUtil;
import com.seecen.HJM.util.TypeConversionUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private EmailService emailService;
    @Autowired
    private MinioService minioService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    //用户注册接口
    @Override
    public String registerUser(User user) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", user.getUsername());
        User existUser = userMapper.selectOne(queryWrapper);
        if (existUser != null) {
            return MessageConstant.USERNAME + MessageConstant.ALREADY_EXISTS; // 用户名已存在
        }

        //加密密码
        String encodePassword = PasswordEncoderUtil.encode(user.getPassword());
        user.setPassword(encodePassword);

        // 设置默认值
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        user.setUserStatus(0); // 默认启用
        // 插入用户信息，新增成功
        int insert = userMapper.insert(user);
        return insert > 0 ? "success" : MessageConstant.UNKNOWN_ERROR;
    }

    @Override
    public DataVo<String> loginByUsername(UserLoginDTO loginDTO) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, loginDTO.getUsername());
        User user = userMapper.selectOne(queryWrapper);
        // 2. 验证用户是否存在
        if (user == null) {
            return DataVo.error(MessageConstant.USERNAME + MessageConstant.NOT_EXIST);
        }

        // 3. 验证密码
        if (!PasswordEncoderUtil.matches(loginDTO.getPassword(), user.getPassword())) {
            return DataVo.error(MessageConstant.PASSWORD + MessageConstant.ERROR);
        }

        // 4. 生成JWT令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.ROLE, RoleEnum.USER.getRole());
        claims.put(JwtClaimsConstant.USER_ID, user.getUserId());
        claims.put(JwtClaimsConstant.USERNAME, user.getUsername());
        claims.put(JwtClaimsConstant.EMAIL, user.getEmail());
        String token = JwtUtil.generateToken(claims);
        // 将token存入redis
        stringRedisTemplate.opsForValue().set(token, token, 6, TimeUnit.HOURS);
        // 5. 返回成功结果
        return DataVo.success(MessageConstant.LOGIN + MessageConstant.SUCCESS, token);
    }

    @Override
    public DataVo<String> loginByEmail(UserLoginDTO loginDTO) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getEmail, loginDTO.getEmail());
        User user = userMapper.selectOne(queryWrapper);

        // 2. 验证用户是否存在
        if (user == null) {
            return DataVo.error(MessageConstant.EMAIL + MessageConstant.NOT_EXIST);
        }

        // 3. 验证密码
        if (!PasswordEncoderUtil.matches(loginDTO.getPassword(), user.getPassword())) {
            return DataVo.error(MessageConstant.PASSWORD + MessageConstant.ERROR);
        }
        // 4. 生成JWT令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.ROLE, RoleEnum.USER.getRole());
        claims.put(JwtClaimsConstant.USER_ID, user.getUserId());
        claims.put(JwtClaimsConstant.USERNAME, user.getUsername());
        claims.put(JwtClaimsConstant.EMAIL, user.getEmail());
        String token = JwtUtil.generateToken(claims);
        // 将token存入redis
        stringRedisTemplate.opsForValue().set(token, token, 6, TimeUnit.HOURS);

        // 5. 返回成功结果
        return DataVo.success(MessageConstant.LOGIN + MessageConstant.SUCCESS, token);
    }

    @Override
    public DataVo resetUserPassword(UserResetPasswordDTO userResetPasswordDTO) {
        // 删除Redis中的验证码
        stringRedisTemplate.delete("verificationCode:" + userResetPasswordDTO.getEmail());

        User user = userMapper.selectOne(new QueryWrapper<User>().eq("email", userResetPasswordDTO.getEmail()));
        if (user == null) {
            return DataVo.error(MessageConstant.EMAIL + MessageConstant.NOT_EXIST);
        }

        if (!userResetPasswordDTO.getRepeatPassword().equals(userResetPasswordDTO.getNewPassword())) {
            return DataVo.error(MessageConstant.PASSWORD_NOT_MATCH);
        }

        // 使用BCrypt加密替代MD5（核心改良）
        String encodedPassword = PasswordEncoderUtil.encode(userResetPasswordDTO.getNewPassword());

        if (userMapper.update(new User()
                        .setPassword(encodedPassword)  // 使用工具类加密后的密码
                        .setUpdateTime(LocalDateTime.now()),
                new QueryWrapper<User>().eq("id", user.getUserId())) == 0) {
            return DataVo.error(MessageConstant.PASSWORD + MessageConstant.RESET + MessageConstant.FAILED);
        }

        return DataVo.success(MessageConstant.PASSWORD + MessageConstant.RESET + MessageConstant.SUCCESS);
    }

    @Override
    public DataVo sendVerificationCode(String email) {
        String verificationCode = emailService.sendVerificationCodeEmail(email);
        if (verificationCode == null) {
            return DataVo.error(MessageConstant.EMAIL_SEND_FAILED);
        }

        // 将验证码存储到Redis中，设置过期时间为5分钟
        stringRedisTemplate.opsForValue().set("verificationCode:" + email, verificationCode, 5, TimeUnit.MINUTES);
        return DataVo.success(MessageConstant.EMAIL_SEND_SUCCESS);
    }

    @Override
    public boolean verifyVerificationCode(String email, String verificationCode) {
        String storedCode = stringRedisTemplate.opsForValue().get("verificationCode:" + email);
        return storedCode != null && storedCode.equals(verificationCode);

    }

    @Override
    @CacheEvict(cacheNames = {"userCache", "userFavoriteCache", "songCache", "artistCache", "playlistCache"}, allEntries = true)
    public DataVo logout(String token) {
        // 注销token
        Boolean result = stringRedisTemplate.delete(token);
        if (result != null && result) {
            return DataVo.success(MessageConstant.LOGOUT + MessageConstant.SUCCESS);
        } else {
            return DataVo.error(MessageConstant.LOGOUT + MessageConstant.FAILED);
        }
    }


    @Override
    public Boolean register(User user) {
        // 检查用户名是否已存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", user.getUsername());
        User existUser = userMapper.selectOne(queryWrapper);
        if (existUser != null) {
            return false;
        }
        //加密密码
        String encodePassword = PasswordEncoderUtil.encode(user.getPassword());
        user.setPassword(encodePassword);
        // 设置默认值
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        user.setUserStatus(0); // 默认启用
        // 插入用户信息，新增成功
        int insert = userMapper.insert(user);
        return insert > 0;
    }

    @Override
    public List<User> searchUsers(String keyword) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper
                .eq("username", keyword)
                .or()
                .eq("phone", keyword)
                .or()
                .eq("email", keyword));
        return userMapper.selectList(queryWrapper);
    }

    @Override
    public boolean updateUser(Long userId, String username, String userAvatar, String phone, String password, String email, Integer userStatus,LocalDateTime updateTime,String introduction) {
        User user = new User();
        user.setUserId(userId);

        // 只设置非空的字段
        boolean hasUpdate = false;

        if (username != null) {
            user.setUsername(username);
            hasUpdate = true;
        }
        if (userAvatar != null) {
            user.setUserAvatar(userAvatar);
            hasUpdate = true;
        }
        if (phone != null) {
            user.setPhone(phone);
            hasUpdate = true;
        }
        // 关键修改：如果传入密码，则用BCrypt加密后再存储
        if (password != null) {
            // 使用你的PasswordEncoderUtil加密密码
            user.setPassword(PasswordEncoderUtil.encode(password));
            hasUpdate = true;
        }
        if (email != null) {
            user.setEmail(email);
            hasUpdate = true;
        }
        if (userStatus != null) {
            user.setUserStatus(userStatus);
            hasUpdate = true;
        }
        if (updateTime != null) {
            user.setUpdateTime(updateTime);
            hasUpdate = true;
        }
        if (introduction != null) {
            user.setIntroduction(introduction);
            hasUpdate = true;
        }
        // 如果没有字段需要更新，返回false
        if (!hasUpdate) {
            return false;
        }
        return userMapper.updateById(user) > 0;
    }

    @Override
    public boolean deleteUser(Long userId) {
        return userMapper.deleteById(userId) > 0;
    }


    @Override
    public long getActiveUsersThisMonth() {
        LocalDateTime startOfMonth = LocalDateTime.now().with(TemporalAdjusters.firstDayOfMonth());
        LocalDateTime endOfMonth = LocalDateTime.now().with(TemporalAdjusters.lastDayOfMonth());
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.ge("create_time", startOfMonth)
                .le("create_time", endOfMonth);
        return userMapper.selectCount(queryWrapper);
    }

    @Override
    public long getTotalUsers() {
        return userMapper.selectCount(null);
    }

    @Override
    public List<User> findWithUserItems(IPage<User> userIPage, QueryWrapper<User> queryWrapper) {
        return userMapper.selectUserByPage(userIPage, queryWrapper);
    }


//错的一号修好
//    @Override
//    @CacheEvict(cacheNames = "userCache", allEntries = true)
//    public DataVo updateUserAvatar(String avatarUrl) {
//        Map<String, Object> map = ThreadLocalUtil.get();
//        System.out.println(map);
//        Object userIdObj = map.get(JwtClaimsConstant.USER_ID);
//        Long userId = TypeConversionUtil.toLong(userIdObj);
//
//        User user = userMapper.selectById(userId);
//        String userAvatar = user.getUserAvatar();
//        if (userAvatar != null && !userAvatar.isEmpty()) {
//            minioService.deleteFile(userAvatar);
//        }
//
//        if (userMapper.update(new User().setUserAvatar(avatarUrl).setUpdateTime(LocalDateTime.now()),
//                new QueryWrapper<User>().eq("id", userId)) == 0) {
//            return DataVo.error(MessageConstant.UPDATE + MessageConstant.FAILED);
//        }
//        return DataVo.success(MessageConstant.UPDATE + MessageConstant.SUCCESS);
//    }

    //头像上传
    @Override
    public DataVo updateUserAvatar(Long userId, String avatarUrl) {
        User user = userMapper.selectById(userId);
        String userAvatar = user.getUserAvatar();
        if (userAvatar != null && !userAvatar.isEmpty()) {
            minioService.deleteFile(userAvatar);
        }
        user.setUserAvatar(avatarUrl);
        if (userMapper.updateById(user) == 0) {
            return DataVo.error(MessageConstant.UPDATE + MessageConstant.FAILED);
        }
        return DataVo.success(MessageConstant.UPDATE + MessageConstant.SUCCESS);
    }

    /**
     * 用户信息
     *
     * @return 结果
     */
    @Override
    public DataVo<UserVO> userInfo() {
        Map<String, Object> map = ThreadLocalUtil.get();
        Object userIdObj = map.get(JwtClaimsConstant.USER_ID);
        Long userId = TypeConversionUtil.toLong(userIdObj);
        User user = userMapper.selectById(userId);
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);

        return DataVo.success(userVO);
    }
}
